package com.hrhx.springboot;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints;

class CalcCurveFitting implements TestCase  
{  
   public CalcCurveFitting()  
   {  
      System.out.print("本算例用于计算多项式曲线拟合。正在初始化 计算数据(" + arrayLength + "点, " + degree + "阶)... ...");  
      inputDataX = new double[arrayLength];  
      //      inputDataX = new double[] {1, 2, 3, 4, 5, 6, 7};  
      inputDataY = new double[inputDataX.length];  
      double[] factor = new double[degree + 1];    // N阶多项式会有N+1个系数，其中之一为常数项  
      for(int index = 0; index < factor.length; index ++)  
      {  
         factor[index] = index + 1;  
      }  
      for(int index = 0; index < inputDataY.length; index ++)  
      {  
         inputDataX[index] = index * 0.00001;  
         inputDataY[index] = calcPoly(inputDataX[index], factor);    // y = sum(x[n) * fact[n])  
         // System.out.print(inputDataY[index] + ", ");  
      }  
      points = new WeightedObservedPoints();  
      for(int index = 0; index < inputDataX.length; index ++)  
      {  
         points.add(inputDataX[index], inputDataY[index]);  
      }  
      System.out.println("初始化完成");  
   }  
  
   @Override  
   public List<Object> getParams()  
   {  
      List<Object> params = new ArrayList<Object>();  
      params.add(points);  
      return params;  
   }  
  
   @Override  
   public Object run(List<Object> params) throws Exception  
   {  
      PolynomialCurveFitter fitter = PolynomialCurveFitter.create(degree);  
      WeightedObservedPoints points = (WeightedObservedPoints)params.get(0);  
      double[] result = fitter.fit(points.toList());  
      return result;  
   }  
  
   @Override  
   public void printResult(Object result)  
   {  
      for(double data : (double[])result)  
      {  
         System.out.println(data);  
      }  
   }  
  
   private double calcPoly(double x, double[] factor)  
   {  
      double y = 0;  
      for(int deg = 0; deg < factor.length; deg ++)  
      {  
         y += Math.pow(x, deg) * factor[deg];  
      }  
  
      return y;  
   }  
  
   private double[] inputDataX = null;  
   private double[] inputDataY = null;  
   private WeightedObservedPoints points = null;  
  
   private final int arrayLength = 200000;  
   private final int degree = 5;    // 阶数  
  
}  